#include "bdd.h"
#include <sys/stat.h>
#include <fcntl.h>

#ifndef __APPLE__
#include <sys/types.h>
#include <unistd.h>
#endif

#define PWET 1024


byte
write_bdd (subbase * b)
{
  subbase *s, *par = NULL;
  row *r;
  int w;
  char *str_tmp;
  char nrow = 0x1C, nsub = 0x1D, nval = 0x1E, nparent = 0x1F;

  if (!b)
    return 0;

  str_tmp = malloc (strlen (b->ident) + strlen (bdd_path) + 1);
  strcpy (str_tmp, bdd_path);
  strcat (str_tmp, b->ident);
  // puts (str_tmp);

  w = open (str_tmp, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU);
  free (str_tmp);
  if (w == -1)
    return 0;
  s = b;

  while (1)
    {
      if (s)
	{
	  if (s != b)
	    {
	      write (w, &nsub, 1);
	      write (w, s->ident, strlen (s->ident));
	      write (w, &nsub, 1);
	    }
	  for (r = s->rows; r; r = r->next)
	    {
	      write (w, &nrow, 1);
	      write (w, r->ident, strlen (r->ident));
	      write (w, &nval, 1);
	      write (w, r->val, strlen (r->val));
	      write (w, &nrow, 1);
	    }
	  par = s;
	  s = s->enfant;
	}
      else
	{
	  write (w, &nparent, 1);
	  s = par;
	  if (!s || s == b)
	    break;
	  par = s->parent;
	  s = s->next;
	}
    }
  return 1;
}


byte
read_bdd (char *bname, byte mode, byte c_s)
{
  subbase *ptr;
  char *str_tmp;
  int f, len, a, ct, cpt = PWET, tmax;
  char *buffer, nrow = 0x1C, nsub = 0x1D, nval = 0x1E, nparent = 0x1F;
  char *pid = NULL, *pval = NULL, *ptr_id = NULL, *ptr_val = NULL;
  byte flag_sub = 0, flag_row = 0, flag_val = 0;

  str_tmp = malloc (strlen (bname) + strlen (bdd_path) + 1);
  strcpy (str_tmp, bdd_path);
  strcat (str_tmp, bname);

  f = open (str_tmp, O_RDONLY);
  free (str_tmp);
  if (f == -1)
    return 0;

  root_head = add_base (root_head, bname, c_s);
  ptr = root_head->base;
  root_head->mode = mode;

  buffer = malloc (PWET + 1);
  while (1)
    {
      ct = read (f, buffer + cpt - PWET, PWET);
      if (ct < PWET)
	break;
      cpt += PWET;
      buffer = realloc (buffer, cpt + 1);
    }

  close (f);

  tmax = cpt - PWET + ct;

  for (a = 0; a < tmax; a++)
    {
      if (buffer[a] == nsub)
	{
	  if (!flag_sub)
	    {
	      flag_sub = 1;
	      ptr_id = buffer + a + 1;
	    }
	  else
	    {
	      if (flag_row || flag_val)
		puts ("database is corrupted");
	      flag_sub = 0;
	      len = (buffer + a) - ptr_id;
	      pid = malloc (len + 1);
	      strncpy (pid, ptr_id, len);
	      pid[len] = 0;
	      ptr->enfant = add_subbase (ptr, ptr->enfant, pid, c_s);
	      ptr = ptr->enfant;
	      free (pid);
	    }
	}
      else if (buffer[a] == nparent)
	{
	  ptr = ptr->parent;

	  if (flag_sub || flag_row || flag_val)
	    puts ("database is corrupted");

	  if (!ptr)
	    break;
	}
      else if (buffer[a] == nrow)
	{
	  if (!flag_row)
	    {
	      flag_row = 1;
	      ptr_id = buffer + a + 1;
	    }
	  else
	    {
	      if (flag_sub || !flag_val)
		puts ("database is corrupted");
	      flag_row = 0;
	      flag_val = 0;
	      len = (ptr_val - 1) - ptr_id;
	      pid = malloc (len + 1);
	      strncpy (pid, ptr_id, len);
	      pid[len] = 0;

	      len = (buffer + a) - ptr_val;
	      pval = malloc (len + 1);
	      strncpy (pval, ptr_val, len);
	      pval[len] = 0;

	      ptr->rows = add_row (ptr->rows, pid, pval, c_s);
	      free (pid);
	      free (pval);
	    }
	}
      else if (buffer[a] == nval)
	{
	  if (flag_sub || !flag_row)
	    puts ("database is corrupted");
	  ptr_val = buffer + a + 1;
	  flag_val = 1;
	}
    }
  free (buffer);
  return 1;
}
